package com.server.net;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import com.server.util.ConfPropertiesUtil;
import com.server.util.LogUtil;

/**
 * netty服务
 */
public class NettyProtobufServer {
    private EventLoopGroup parentGroup;//接收者
    private EventLoopGroup childGroup;//客户端

    public NettyProtobufServer() {

    }

    public void init() {
        //启动监听
        parentGroup = new NioEventLoopGroup(1);//设置1个线程
        childGroup = new NioEventLoopGroup();//如果没有指定，默认是cpu核数的两倍，可以从源码中看到

        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(parentGroup, childGroup);//绑定两个线程组
        serverBootstrap.channel(NioServerSocketChannel.class);//设置nio双向通道
        serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));//不写这行，便不会打印日志
        //设置参数，TCP参数
        serverBootstrap.option(ChannelOption.SO_BACKLOG, 20480);//serverSocketchannel的设置，链接缓冲池的大小
        serverBootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); // 使用内存池
        serverBootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); // 使用内存池
        serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);//socketchannel的设置,维持链接的活跃，清除死链接
        serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);//socketchannel的设置,关闭延迟发送
        serverBootstrap.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(64 * 1024, 128 * 1024));
        serverBootstrap.childHandler(new NettyProtobufServerInitializer());//自定义处理器

        try {
            //启动server绑定端口
            ChannelFuture channelFuture = serverBootstrap.bind(ConfPropertiesUtil.getInstance()._PORT).sync();

            //下面会阻塞，等待服务器链接断开，main方法退出，程序结束
            //关闭监听得channel
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            LogUtil.game.error("Exception", e);
        } finally {
            //关闭事件组，优雅释放线程资源
            parentGroup.shutdownGracefully();
            childGroup.shutdownGracefully();
        }
    }

}
